/*
 * 文件功能说明：
 * 该文件用于测试感为八路灰度传感器的功能。
 * - 通过GPIO32(时钟)和GPIO35(数据)与传感器通信
 * - 读取8位传感器数据并通过串口输出
 * - 传感器特性：扫白线返回高电平(1)，扫黑线返回低电平(0)
 */

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_time.h"
#include "iot_watchdog.h"
#include "iot_errno.h"

// 感为八路灰度传感器GPIO定义
#define GW_GRAY_GPIO_CLK 11  // 时钟信号：GPIO11
#define GW_GRAY_GPIO_DAT 12  // 数据信号：GPIO12
#define GPIO_FUNC 0          // GPIO功能模式设置

/*
 * 函数：gw_gray_serial_read_simple
 * 功能：读取感为八路灰度传感器的8bit数据
 * 输入：无
 * 输出：unsigned char - 8位传感器数据，每bit代表一路传感器状态
 *       bit0-bit7分别对应传感器1-8路，1表示检测到白线，0表示检测到黑线
 */
static unsigned char gw_gray_serial_read_simple(void)
{
    unsigned char ret = 0;
    for (int i = 0; i < 8; ++i) {
        IoTGpioSetOutputVal(GW_GRAY_GPIO_CLK, IOT_GPIO_VALUE0); // 输出时钟下降沿
        
        IotGpioValue data_val;
        IoTGpioGetInputVal(GW_GRAY_GPIO_DAT, &data_val); // 读取数据
        if (data_val == IOT_GPIO_VALUE1) {
            ret |= (1 << i); // 将数据存到ret的第i位bit
        }
        
        IoTGpioSetOutputVal(GW_GRAY_GPIO_CLK, IOT_GPIO_VALUE1); // 输出时钟上升沿
        hi_udelay(5); // 延时5微秒
    }
    return ret;
}

/*
 * 函数：gw_gray_sensor_init
 * 功能：初始化感为八路灰度传感器的GPIO配置
 * 输入：无
 * 输出：无
 */
static void gw_gray_sensor_init(void)
{
    // 初始化时钟GPIO为输出模式
    IoTGpioInit(GW_GRAY_GPIO_CLK);
    hi_io_set_func(GW_GRAY_GPIO_CLK, GPIO_FUNC);
    IoTGpioSetDir(GW_GRAY_GPIO_CLK, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GW_GRAY_GPIO_CLK, IOT_GPIO_VALUE0);
    
    // 初始化数据GPIO为输入模式，启用上拉
    IoTGpioInit(GW_GRAY_GPIO_DAT);
    hi_io_set_func(GW_GRAY_GPIO_DAT, GPIO_FUNC);
    IoTGpioSetDir(GW_GRAY_GPIO_DAT, IOT_GPIO_DIR_IN);
    hi_io_set_pull(GW_GRAY_GPIO_DAT, HI_IO_PULL_UP);
    
    printf("Gray sensor test initialized: CLK=GPIO%d, DAT=GPIO%d\r\n", GW_GRAY_GPIO_CLK, GW_GRAY_GPIO_DAT);
}

/*
 * 函数：print_sensor_data
 * 功能：格式化输出传感器数据
 * 输入：sensor_data - 8位传感器数据
 * 输出：无
 */
static void print_sensor_data(unsigned char sensor_data)
{
    printf("Sensor data: ");
    // 从左到右显示传感器状态 (bit7 到 bit0)
    for (int i = 7; i >= 0; i--) {
        printf("%d", (sensor_data >> i) & 0x1);
        if (i == 4) printf(" "); // 在中间添加空格便于阅读
    }
    printf(" (0x%02X) ", sensor_data);
    
    // 分析传感器状态
    int black_line_count = 0;
    int line_position = 0;
    
    // 计算检测到黑线的传感器数量和位置
    for (int i = 0; i < 8; i++) {
        if ((sensor_data & (1 << i)) == 0) { // 检测到黑线（低电平）
            black_line_count++;
            line_position += i;
        }
    }
    
    if (black_line_count > 0) {
        line_position = line_position / black_line_count; // 计算平均位置
        printf("- Black line detected: count=%d, avg_pos=%d", black_line_count, line_position);
        
        // 判断转向建议
        if (line_position < 3) {
            printf(" -> Turn LEFT");
        } else if (line_position > 4) {
            printf(" -> Turn RIGHT");
        } else {
            printf(" -> Go FORWARD");
        }
    } else {
        printf("- No black line detected -> Go FORWARD");
    }
    
    printf("\r\n");
}

/*
 * 函数：GrayTestTask
 * 功能：灰度传感器测试任务
 * 输入：param - 任务参数（未使用）
 * 输出：无
 */
void *GrayTestTask(void* param)
{
    printf("=== 感为八路灰度传感器测试开始 ===\r\n");
    printf("传感器位置: [7][6][5][4] [3][2][1][0]\r\n");
    printf("传感器特性: 1=白线, 0=黑线\r\n");
    printf("GPIO配置: CLK=GPIO32, DAT=GPIO35\r\n");
    printf("=====================================\r\n");
    
    // 初始化传感器
    gw_gray_sensor_init();
    
    // 等待传感器稳定
    hi_sleep(1000);
    
    unsigned char sensor_data = 0;
    int test_counter = 0;
    
    while (1) {
        // 读取传感器数据
        sensor_data = gw_gray_serial_read_simple();
        
        // 输出传感器数据
        printf("[%04d] ", ++test_counter);
        print_sensor_data(sensor_data);
        
        // 延时500ms
        hi_sleep(500);
        
        // 看门狗
        IoTWatchDogDisable();
    }
    
    return NULL;
}

/*
 * 函数：GrayTestDemo
 * 功能：启动灰度传感器测试演示
 * 输入：无
 * 输出：无
 */
void GrayTestDemo(void)
{
    osThreadAttr_t attr;
    
    attr.name = "GrayTestTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096;
    attr.priority = 25;
    
    if (osThreadNew(GrayTestTask, NULL, &attr) == NULL) {
        printf("[GrayTestDemo] Failed to create GrayTestTask!\n");
    }
}

// 注册应用特性初始化
APP_FEATURE_INIT(GrayTestDemo);
